<?php

namespace App\Models\System;

use App\Components\Redis;
use Illuminate\Database\Eloquent\Model;

class SystemUser extends Model
{
    const TOKEN_CACHE_PREFIX = 'MODELS:SYSTEM:SYSTEMUSER:TOKEN:';

    const TOKEN_COOKIE_KEY = 'SSID';

    protected $table = 'system_user';

    public static function generateToken(int $userId): string
    {
        $userInfo = self::select('id', 'username', 'password', 'status', 'updated_at')
            ->where('id', $userId)->first();
        if (!isset($userInfo->id)) {
            return '';
        }
        $userInfo = $userInfo->toArray();

        $token = http_build_query($userInfo);
        $token = md5($token);
        $token = strtoupper($token);
        return $token;
    }

    public static function saveToken(int $userId, string $token, bool $isRemember = false): bool
    {
        $cacheKey = self::TOKEN_CACHE_PREFIX . $token;
        $cookieKey = strtoupper($_ENV['app_name']) . '_' . self::TOKEN_COOKIE_KEY;
        if ($isRemember === true) {
            Redis::setex($cacheKey, 86400 * 3, json_encode(['id' => $userId, 'remember' => 1]));
            setcookie($cookieKey, $token, time() + 86400 * 7, '/', '', false, true);
        } else {
            Redis::setex($cacheKey, Redis::mediumTime(3), json_encode(['id' => $userId, 'remember' => 0]));
            setcookie($cookieKey, $token, time() + 3600 * 7, '/', '', false, true);
        }
        return true;
    }

    public static function getIdByToken(): int
    {
        $cookieKey = strtoupper($_ENV['app_name']) . '_' . self::TOKEN_COOKIE_KEY;
        $token = $_COOKIE[$cookieKey] ?? '';
        if ($token == '') {
            return 0;
        }
        $cacheKey = self::TOKEN_CACHE_PREFIX . $token;
        $cacheRs = Redis::get($cacheKey);
        if ($cacheRs !== false && $cacheRs !== null) {
            $cacheRs = json_decode($cacheRs, true);
            if (!isset($cacheRs['id']) || !isset($cacheRs['remember'])) {
                return 0;
            }
            $expire = Redis::ttl($cacheKey);
            if ($cacheRs['remember'] == 1) {
                if ($expire <= 86400 * 2) {
                    Redis::expire($cacheKey, 86400 * 3);
                }
            } else {
                if ($expire <= 3600 * 2) {
                    Redis::expire($cacheKey, Redis::mediumTime(3));
                }
            }
            return $cacheRs['id'];
        } else {
            $infoRs = self::select('id')
                ->where('token', $token)
                ->where('status', 1)->first();
            if (!isset($infoRs->id)) {
                return 0;
            }
            self::saveToken($infoRs->id, $token);
            return $infoRs->id;
        }

        return 0;
    }
}
